/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2018-2022. All rights reserved.
 * Description: 节点内建链实现对外头文件
 * Author: wangwenwen
 * Create: 2018-06-26
 */

#ifndef TRANSPORT_P2P_PUB_H
#define TRANSPORT_P2P_PUB_H

#include <sstream>

#include "transport_base_pub.h"

namespace hccl {

typedef enum {
    EX_IPCMEN_SIZE = 0,    /**< ipcMenSize */
    EX_NOTIFY_SIZE = 1,   /**< notifySize */
    EX_EXDATA_SIZE = 2    /**< exDataSize */
} ExInfoType;
struct ExchangeInfoSize
{
    u32 ipcMenSize;
    u32 notifySize;
    u32 exDataSize;

    bool compare(ExchangeInfoSize &that) {
        if ((this->ipcMenSize != that.ipcMenSize) ||
            (this->notifySize != that.notifySize) ||
            (this->exDataSize != that.exDataSize)) {
            return false;
        }
        return true;
    }
};

class TransportP2p : public TransportBase {
public:
    explicit TransportP2p(DispatcherPub *dispatcher,
                      const std::unique_ptr<NotifyPool> &notifyPool,
                      MachinePara &machinePara,
                      std::chrono::milliseconds timeout);
    ~TransportP2p() override;

    HcclResult Init() override;

    HcclResult TxDataSignal(Stream &stream) override;
    HcclResult RxDataSignal(Stream &stream) override;

    HcclResult TxAck(Stream &stream) override;
    HcclResult RxAck(Stream &stream) override;

    HcclResult TxAsync(UserMemType dstMemType, u64 dstOffset, const void *src, u64 len,
                                  Stream &stream) override;
    HcclResult TxAsync(std::vector<TxMemoryInfo>& txMems, Stream &stream) override;

    HcclResult RxAsync(UserMemType srcMemType, u64 srcOffset, void *dst, u64 len,
                                  Stream &stream) override;
    HcclResult RxAsync(std::vector<RxMemoryInfo>& rxMems, Stream &stream) override;

    HcclResult DataReceivedAck(Stream &stream) override;

    HcclResult TxData(UserMemType dstMemType, u64 dstOffset, const void *src, u64 len, Stream &stream) override;

    HcclResult RxData(UserMemType srcMemType, u64 srcOffset, void *dst, u64 len, Stream &stream) override;

    HcclResult TxPrepare(Stream &stream) override;
    HcclResult RxPrepare(Stream &stream) override;

    HcclResult TxDone(Stream &stream) override;
    HcclResult RxDone(Stream &stream) override;

    HcclResult GetRemoteMem(UserMemType memType, void **remotePtr) override;
    HcclResult GetRemoteMem(std::vector<void *> *remotePtrVec) override;

    HcclResult GetRemoteMemSize(UserMemType memType, u64 &size) override;

    HcclResult WriteAsync(struct Transport::Buffer &remoteBuf, struct Transport::Buffer &localBuf, Stream &stream);
    HcclResult WriteSync(struct Transport::Buffer &remoteBuf, struct Transport::Buffer &localBuf, Stream &stream);

    HcclResult ReadAsync(struct Transport::Buffer &localBuf, struct Transport::Buffer &remoteBuf, Stream &stream);
    HcclResult ReadSync(struct Transport::Buffer &localBuf, struct Transport::Buffer &remoteBuf, Stream &stream);
    HcclResult ReadReduceSync(struct Transport::Buffer &localBuf, struct Transport::Buffer &remoteBuf,
        const HcclDataType datatype, HcclReduceOp redOp, Stream &stream);

    HcclResult PostReady(Stream &stream);
    HcclResult WaitReady(Stream &stream);

    HcclResult PostFin(Stream &stream);
    HcclResult WaitFin(Stream &stream);

    HcclResult Post(u32 notifyIdx, Stream &stream) override;
    HcclResult Wait(u32 notifyIdx, Stream &stream) override;

protected:
    HcclResult FillExchangeDataTotalSize() override;

    HcclResult ConstructExchangeForSend() override;
    HcclResult ConstructIpcMemInfoForSend(void *ptr, u64 size, u8*& exchangeDataPtr, u64& exchangeDataBlankSize);
    HcclResult ConstructIntraProcMemInfoForSend(void *ptr, u64 size, u8*& exchangeDataPtr, u64& exchangeDataBlankSize);
    HcclResult ConstructNotifyInfoForSend(u8*& exchangeDataPtr, u64& exchangeDataBlankSize);
    HcclResult ConstructNotifyVectorInfoForSend(u8*& exchangeDataPtr, u64& exchangeDataBlankSize);
    HcclResult ConstructDataLenForSend(u8*& exchangeDataPtr, u64& exchangeDataBlankSize);

    HcclResult ParseReceivedExchangeData() override;
    HcclResult ParseIpcMemInfo(void **memPtr, u64 &size, u8 *memName, u64 &offset, u8 *&exchangeDataPtr,
        u64 &exchangeDataBlankSize);
    HcclResult ParseIntraProcMemInfo(u64* addr, u64* size, u8*& exchangeDataPtr, u64& exchangeDataBlankSize);
    HcclResult ParseNotifyInfo(u8*& exchangeDataPtr, u64& exchangeDataBlankSize);
    HcclResult ParseNotifyVectorInfo(u8*& exchangeDataPtr, u64& exchangeDataBlankSize);
    HcclResult ParseCheckDataLen(ExchangeInfoSize &remoteInfoSize, u8*& exchangeDataPtr, u64& exchangeDataBlankSize);

    HcclResult GetLocalNotify(std::vector<HcclSignalInfo> &localNotify) override;
    HcclResult GetRemoteNotify(std::vector<HcclSignalInfo> &localNotify) override;

    HcclResult WaitPeerMemConfig(void **memPtr, const u8 *memName, uint64_t size, u64 offset);
    HcclResult ExchangeMemAndNotifyMesg();
    HcclResult SendIpcMemMesg(void *ptr, u64 size) const;
    HcclResult RecvIpcMemMesg(void **memPtr, u8 *memName, u64 &offset);
    HcclResult SendMemMesgWithoutIpc(void *ptr, u64 size) const;
    HcclResult RecvMemMesgWithoutIpc(u64 &addr, u8 *memName, u64 &offset);
    HcclResult ExchangeMemAndNotifyWithIpc();
    HcclResult ExchangeMemAndNotifyWithoutIpc();
    virtual HcclResult SignalRecord(std::shared_ptr<RemoteNotify> &remoteSignal, u64 remoteSignalAddr, u64 remoteSignalOffset, Stream &stream);
    void SetTransportRelationship();
    HcclResult SetLinkType();
    HcclResult CreateNotifyValueBuffer();
    HcclResult SumCheckSizeAndConsisten(ExInfoType exInfoType, u32 rightInfoSize, u64 &blankSizeRecord,
        u64 exchangeDataBlankSize);
    void SetUseSdmaToSignalRecord();

    void *remoteInputPtr_;
    void *remoteOutputPtr_;
    std::vector<void*> remoteIpcMemPtrVector_;
    u64 remoteInputSize_;
    u64 remoteOutputSize_;
    std::vector<u64> remoteIpcMemSizeVector_;
    u64 remoteOutputOffsetValue_;
    u64 remoteInputOffsetValue_;
    std::vector<u64> remoteIpcMemOffsetValueVector_;
    bool useSdmaToSignalRecord_{false};
private:
    SecIpcName_t remoteOutputMemName_;
    SecIpcName_t remoteInputMemName_;
    std::vector<SecIpcName_t> remoteIpcMemNameVector_;
    static std::array<DeviceMem, MAX_MODULE_DEVICE_NUM> notifyValueMem_;
    static std::array<std::mutex, MAX_MODULE_DEVICE_NUM> notifyValueMutex_;
    const u64 notifyValueSize_{LARGE_PAGE_MEMORY_MIN_SIZE}; // 避免申请小页内存。最小2*1024*1024
    static std::array<Referenced, MAX_MODULE_DEVICE_NUM> instanceRef_; // 实例计数，用于释放静态资源
    ExchangeInfoSize exchangeInfoSize_ {0};
};
}  // namespace hccl

#endif /* TRANSPORT_P2P_PUB_H */
